bitkeeper revision 1.1053.1.1 (40ee75a9YghVZFFolzFjyJngpxAbKg)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Fri, 9 Jul 2004 10:38:33 +0000 (10:38 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Fri, 9 Jul 2004 10:38:33 +0000 (10:38 +0000)
Move to new model of network and vif control using shell scripts.

17 files changed:
.rootkeys
tools/examples/Makefile
tools/examples/network [new file with mode: 0755]
tools/examples/vif-bridge [new file with mode: 0755]
tools/examples/vifctl
tools/examples/xend-config.sxp [new file with mode: 0644]
tools/examples/xmdefaults
tools/examples/xmnetbsd
tools/misc/netfix
tools/python/xen/util/ip.py
tools/python/xen/xend/Vifctl.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/XendRoot.py
tools/python/xen/xend/server/SrvDaemon.py
tools/python/xen/xend/server/SrvServer.py
tools/python/xen/xend/server/netif.py
tools/python/xen/xm/create.py

index f953e63aea719105dfbc695606fe1e94a8627431..a34d19ce0758f858a3dcbd945c860a0344ec7aea 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 401d7e160vaxMBAUSLSicuZ7AQjJ3w tools/examples/Makefile
 401d7e16UgeqroJQTIhwkrDVkoWgZQ tools/examples/README
 405ff55dawQyCHFEnJ067ChPRoXBBA tools/examples/init.d/xend
+40ee75a9xFz6S05sDKu-JCLqyVTkDA tools/examples/network
+40ee75a967sxgcRY4Q7zXoVUaJ4flA tools/examples/vif-bridge
 40e15b7edWEtBf_oe3eBwGKuh1dyzQ tools/examples/vifctl
+40ee75a93cqxHp6MiYXxxwR5j2_8QQ tools/examples/xend-config.sxp
 40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults
 40dfd40auJwNnb8NoiSnRkvZaaXkUg tools/examples/xmnetbsd
 3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxc/Makefile
index 4df04eed55bd88e23f7fea8d458ffe6f3fbee33e..f7c3fd74206fc79f9b5134b42ea15208c4f4ece6 100644 (file)
@@ -1,35 +1,35 @@
 
 INSTALL  = $(wildcard *.py)
 
-ETC     = xmdefaults
-ETCDIR   = /etc/xen
-
 INITD    = init.d/xend
 
-XEND     = vifctl
-XEND_DIR = $(ETCDIR)/xend
+XEN_CONFIG_DIR  = /etc/xen
+XEN_CONFIGS = xmdefaults xmnetbsd xend-config.sxp
+
+XEN_SCRIPT_DIR = /etc/xen
+XEN_SCRIPTS = vifctl network vif-bridge
 
 all: 
 
-install: all install-initd install-etc install-xend
+install: all install-initd install-configs install-scripts
 
 install-initd:
        mkdir -p $(prefix)/etc/init.d
        install -m0755 $(INITD) $(prefix)/etc/init.d
 
-install-etc:
-       mkdir -p $(prefix)$(ETCDIR)
-       mkdir -p $(prefix)$(ETCDIR)/auto
-       for i in $(ETC); \
-           do [ -a $(prefix)/$(ETCDIR)/$$i ] || \
-           install -m0644 $$i $(prefix)$(ETCDIR); \
+install-configs:
+       mkdir -p $(prefix)$(XEN_CONFIG_DIR)
+       mkdir -p $(prefix)$(XEN_CONFIG_DIR)/auto
+       for i in $(XEN_CONFIGS); \
+           do [ -a $(prefix)/$(XEN_CONFIG_DIR)/$$i ] || \
+           install -m0644 $$i $(prefix)$(XEN_CONFIG_DIR); \
        done
 
-install-xend:
-       mkdir -p $(prefix)$(XEND_DIR)
-       for i in $(XEND); \
-           do [ -a $(prefix)/$(XEND_DIR)/$$i ] || \
-           install -m0755 $$i $(prefix)$(XEND_DIR); \
+install-scripts:
+       mkdir -p $(prefix)$(XEN_SCRIPT_DIR)
+       for i in $(XEN_SCRIPTS); \
+           do [ -a $(prefix)/$()/$$i ] || \
+           install -m0755 $$i $(prefix)$(XEN_SCRIPT_DIR); \
        done
 
 clean:
diff --git a/tools/examples/network b/tools/examples/network
new file mode 100755 (executable)
index 0000000..49ce29d
--- /dev/null
@@ -0,0 +1,165 @@
+#!/bin/sh
+#============================================================================
+# Example Xen network start/stop script.
+# Xend calls a network script when it starts.
+# This is the default script.
+#
+# /etc/xen/network (start|stop|status) {VAR=VAL}*
+#
+# Vars:
+#
+# bridge     The bridge to use (default xen-br0).
+# netdev     The interface to add to the bridge (default eth0).
+# antispoof  Whether to use iptables to prevent spoofing (default yes).
+#
+# start:
+# Creates the bridge and enslaves netdev to it.
+# Copies the IP addresses from netdev to the bridge.
+# Deletes the routes to netdev and adds them on bridge.
+#
+# stop:
+# Removes netdev from the bridge.
+# Deletes the routes to bridge and adds them to netdev.
+#
+# status:
+# Print ifconfig for netdev and bridge.
+# Print routes.
+#
+#============================================================================
+
+# Exit if anything goes wrong.
+set -e 
+
+# First arg is the operation.
+OP=$1
+shift
+
+# Pull variables in args in to environment.
+for arg ; do export "${arg}" ; done
+
+bridge=${bridge:-xen-br0}
+netdev=${netdev:-eth0}
+antispoof=${antispoof:-yes}
+
+echo "network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof"
+
+# Usage: transfer_addrs src dst
+# Copy all IP addresses (including aliases) from device $src to device $dst.
+transfer_addrs () {
+    local src=$1
+    local dst=$2
+    # Don't bother if $dst already has IP addresses.
+    if ip addr show dev ${dst} | egrep -q '^ *inet' ; then
+        return
+    fi
+    # Address lines start with 'inet' and have the device in them.
+    # Replace 'inet' with 'ip addr add' and change the device name $src
+    # to 'dev $src'.
+    ip addr show dev ${src} | egrep '^ *inet' | sed -e "
+s/inet/ip addr add/
+s/${src}/dev ${dst}/
+" | sh -e
+}
+
+# Usage: transfer_routes src dst
+# Get all IP routes to device $src, delete them, and
+# add the same routes to device $dst.
+# The original routes have to be deleted, otherwise adding them
+# for $dst fails (duplicate routes).
+transfer_routes () {
+    local src=$1
+    local dst=$2
+    # List all routes and grep the ones with $src in.
+    # Stick 'ip route del' on the front to delete.
+    # Change $src to $dst and use 'ip route add' to add.
+    ip route list | grep ${src} | sed -e "
+h
+s/^/ip route del /
+P
+g
+s/${src}/${dst}/
+s/^/ip route add /
+P
+d
+" | sh -e
+}
+
+# Usage: create_bridge dev bridge
+# Create bridge $bridge and add device $dev to it.
+create_bridge () {
+    local dev=$1
+    local bridge=$2
+
+    # Don't create the bridge if it already exists.
+    if ! brctl show | grep -q ${bridge} ; then
+        brctl addbr ${bridge}
+        brctl stp ${bridge} off
+        brctl setfd ${bridge} 0
+        brctl sethello ${bridge} 0
+    fi
+    ifconfig ${bridge} up
+    # Don't add $dev to $bridge if it's already on a bridge.
+    if ! brctl show | grep -q ${dev} ; then
+        brctl addif ${bridge} ${dev}
+    fi
+}
+
+# Usage: antispoofing dev bridge
+# Set the default forwarding policy for $dev to drop.
+# Allow forwarding to the bridge.
+antispoofing () {
+    local dev=$1
+    local bridge=$2
+
+    iptables -P FORWARD DROP
+    iptables -A FORWARD -m physdev --physdev-in ${dev} -j ACCEPT
+}
+
+# Usage: show_status dev bridge
+# Print ifconfig and routes.
+show_status () {
+    local dev=$1
+    local bridge=$2
+    
+    echo '============================================================'
+    ifconfig ${dev}
+    ifconfig ${bridge}
+    echo ' '
+    ip route list
+    echo ' '
+    route -n
+    echo '============================================================'
+}
+
+case ${OP} in
+    start)
+        # Create the bridge and give it the interface IP addresses.
+        # Move the interface routes onto the bridge.
+        create_bridge ${netdev} ${bridge}
+        transfer_addrs ${netdev} ${bridge}
+        transfer_routes ${netdev} ${bridge}
+        
+        if [ ${antispoof} == 'yes' ] ; then
+            antispoofing ${netdev} ${bridge}
+        fi
+        
+        ;;
+    
+    stop)
+        # Remove the interface from the bridge.
+        # Move the routes back to the interface.
+        brctl delif ${bridge} ${netdev}
+        transfer_routes ${bridge} ${netdev}
+
+        # It's not our place to be enabling forwarding...
+        ;;
+
+    status)
+        show_status ${netdev} ${bridge}
+       ;;
+
+    *)
+       echo 'Unknown command: ' ${OP}
+       echo 'Valid commands are: start, stop, status'
+       exit 1
+esac
diff --git a/tools/examples/vif-bridge b/tools/examples/vif-bridge
new file mode 100755 (executable)
index 0000000..2138aa7
--- /dev/null
@@ -0,0 +1,85 @@
+#!/bin/sh
+#============================================================================
+# /etc/xen/vif-bridge
+#
+# Script for configuring a vif in bridged mode.
+# Xend calls a vif script when bringing a vif up or down.
+# This script is the default - but it can be configured for each vif.
+#
+# Example invocation:
+#
+# vif-bridge up domain=VM1 vif=vif1.0 bridge=xen-br0 ip="128.232.38.45/28 10.10.10.55/24"
+#
+#
+# Usage:
+# vif-bridge (up|down) {VAR=VAL}*
+#
+# Vars:
+#
+# domain  name of the domain the interface is on (required).
+# vif     vif interface name (required).
+# mac     vif MAC address (required).
+# bridge  bridge to add the vif to (required).
+# ip      list of IP networks for the vif, space-separated (optional).
+#
+# up:
+# Enslaves the vif interface to the bridge and adds iptables rules
+# for its ip addresses (if any).
+#
+# down:
+# Removes the vif interface from the bridge and removes the iptables
+# rules for its ip addresses (if any).
+#============================================================================
+
+# Exit if anything goes wrong
+set -e 
+
+echo "vif-bridge $*"
+
+# Operation name.
+OP=$1
+shift
+
+# Pull variables in args into environment
+for arg ; do export "${arg}" ; done
+
+# Required parameters. Fail if not set.
+domain=${domain:?}
+vif=${vif:?}
+mac=${mac:?}
+bridge=${bridge:?}
+
+# Optional parameters. Set defaults.
+ip=${ip:-''}   # default to null (do nothing)
+
+# Are we going up or down?
+case $OP in
+    up)
+        brcmd='addif'
+        iptcmd='-A'
+        ;;
+    down)
+        brcmd='delif'
+        iptcmd='-D'
+        ;;
+    *)
+        echo 'Invalid command: ' $OP
+        echo 'Valid commands are: up, down'
+        exit 1
+        ;;
+esac
+
+# Add/remove vif to/from bridge.
+brctl ${brcmd} ${bridge} ${vif}
+
+if [ ${ip} ] ; then
+
+    # If we've been given a list of IP networks, allow pkts with these src addrs.
+    for addr in ${ip} ; do
+        iptables ${iptcmd} FORWARD -m physdev --physdev-in ${vif} -s ${addr} -j ACCEPT
+    done 
+
+    # Always allow us to talk to a DHCP server anyhow.
+    iptables ${iptcmd} FORWARD -m physdev --physdev-in ${vif} -p udp --sport 68 --dport 67 -j ACCEPT
+fi
+
index 3ed0d906232f20ff4d19d8ad7e11e9b11bc92fd5..11aac70fa2f1411129cd5751e10d46b4722dd468 100644 (file)
@@ -16,7 +16,7 @@
 #    added on up and removed on down. The bridge a vif is added to can
 #    be set in the vm config.
 #
-# The default bridge is nbe-br.
+# The default bridge is xen-br0.
 # The default interface is eth0.
 #
 #============================================================================
@@ -33,7 +33,7 @@ class VifControl:
 
     prefix = 'vifctl_'
 
-    DEFAULT_BRIDGE = 'nbe-br'
+    DEFAULT_BRIDGE = 'xen-br0'
     DEFAULT_INTERFACE = 'eth0'
 
     def __init__(self):
diff --git a/tools/examples/xend-config.sxp b/tools/examples/xend-config.sxp
new file mode 100644 (file)
index 0000000..f710a54
--- /dev/null
@@ -0,0 +1,23 @@
+# Xend configuration file.
+
+# Port xend should use for the HTTP interface.
+(xend-port         8000)
+
+# Address xend should listen on.
+# Specifying 'localhost' prevents remote connections.
+# Specifying the empty string '' allows all connections.
+(xend-address      '')
+
+# The script used to start/stop networking for xend.
+(network-script    network)
+
+# The default bridge that virtual interfaces should be connected to.
+(vif-bridge        xen-br0)
+
+# The default script used to control virtual interfaces.
+(vif-script        vif-bridge)
+
+# Whether iptables should be set up to prevent IP spoofing for
+# virtual interfaces. Specify 'yes' or 'no'.
+(vif-antispoof     no)
+
index 640a7390a03338fd4aaa507c177bf7bb203614b7..2c417a7cf888fa4f62ecf3787beaeb3051c82ce3 100644 (file)
@@ -49,7 +49,7 @@ cpu = vmid  # set based on vmid (mod number of CPUs)
 
 # Optionally define mac and/or bridge for the network interfaces.
 # Random MACs are assigned if not given.
-#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
+#vif = [ 'mac=aa:00:00:00:00:11, bridge=xen-br0' ]
 
 #----------------------------------------------------------------------------
 # Define the disk devices you want the domain to have access to, and
index 4f920087b65ae2c160cf18453e066488613559d3..e62de6174eb353f8bdde736b2d6fb6a6ff700352 100644 (file)
@@ -41,7 +41,7 @@ name = "NetBSD VM %d" % vmid
 
 # Optionally define mac and/or bridge for the network interfaces.
 # Random MACs are assigned if not given.
-#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
+#vif = [ 'mac=aa:00:00:00:00:11, bridge=xen-br0' ]
 
 # Specify IP address(es), for the new domain.  You need to
 # configure IP addrs within the domain just as you do normally.  This
index df38e438a1868b2e78a8b95c8e522c09b79e9e04..429f579c023d502d97352a17abb858e5267f9e3e 100644 (file)
@@ -3,7 +3,7 @@
 #============================================================================
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 #============================================================================
-# Move the IP address from eth0 onto the Xen bridge (nbe-br).
+# Move the IP address from eth0 onto the Xen bridge (xen-br0).
 # Only works if the bridge control utils (brctl) have been installed.
 #============================================================================
 
@@ -14,6 +14,9 @@ short_options = 'hvqni:b:c'
 long_options  = ['help', 'verbose', 'quiet',
                  'interface=', 'bridge=', 'create']
 
+defaults['interface'] = 'eth0'
+defaults['bridge'] = 'xen-br0'
+
 def usage():
     print """Usage:
     %s [options]
index 39eb01f944405c8b967851987b012eca309d180a..8f93687139ff2bf4331638bb3effb0bc97df6f1f 100644 (file)
@@ -39,7 +39,7 @@ def _readline(fd):
 When bridging is used, eth0 may not have an IP address,
 as it may have been moved onto the bridge.
 """
-NBE_BRIDGE = 'nbe-br'
+NBE_BRIDGE = 'xen-br0'
 
 def get_current_ipaddr(dev='eth0'):
     """Get the primary IP address for the given network interface.
index 884ed9677dae9fe8280ba19590fb00a12ce08b18..86f68db0b4339fc3d6505b8137c8156ba31142d5 100644 (file)
@@ -1,36 +1,70 @@
-"""Xend interface to the vifctl script.
+"""Xend interface to networking control scripts.
 """
 import os
 import os.path
 import sys
 
-VIFCTL = '/etc/xen/xend/vifctl'
+from xen.xend import XendRoot
+xroot = XendRoot.instance()
 
-def init():
-    """Call 'vifctl init'. Called when xend starts.
+"""Where network control scripts live."""
+SCRIPT_DIR = xroot.network_script_dir
+
+def network(op, script=None, bridge=None, antispoof=None):
+    """Call a network control script.
+    Xend calls this with op 'start' when it starts.
+
+    @param op:        operation (start, stop, status)
+    @param script:    network script name
+    @param bridge:    xen bridge
+    @param antispoof: whether to enable IP antispoofing rules
     """
-    os.system(VIFCTL + ' init ')
+    if op not in ['start', 'stop', 'status']:
+        raise ValueError('Invalid operation:' + op)
+    if script is None:
+        script = xroot.get_network_script()
+    if bridge is None:
+        bridge = xroot.get_vif_bridge()
+    if antispoof is None:
+        antispoof = xroot.get_vif_antispoof()
+    script = os.path.join(SCRIPT_DIR, script)
+    args = [op]
+    args.append("bridge='%s'" % bridge)
+    if antispoof:
+        args.append("antispoof=yes")
+    else:
+        args.append("antispoof=no")
+    args = ' '.join(args)
+    os.system(script + ' ' + args)
+
+def vifctl(op, vif=None, script=None, domain=None, mac=None, bridge=None, ipaddr=[]):
+    """Call a vif control script.
+    Xend calls this when bringing vifs up or down.
 
-def vifctl_args(vif, mac=None, bridge=None, ipaddr=[]):
-    """Construct the argument list for vifctl.
+    @param op:     vif operation (up, down)
+    @param vif:    vif name
+    @param script: name of control script
+    @param domain: name of domain the vif is on
+    @param mac:    vif MAC address
+    @param bridge: bridge to add the vif to
+    @param ipaddr: list of ipaddrs the vif may use
     """
-    args = ['vif=%s' % vif]
-    if mac:
-        args.append('mac=%s' % mac)
+    if op not in ['up', 'down']:
+        raise ValueError('Invalid operation:' + op)
+    if script is None:
+        script = xroot.get_vif_script()
+    if bridge is None:
+        bridge = xroot.get_vif_bridge()
+    script = os.path.join(SCRIPT_DIR, script)
+    args = [op]
+    args.append("vif='%s'" % vif)
+    args.append("domain='%s'" % domain)
+    args.append("mac='%s'" % mac)
     if bridge:
-        args.append('bridge=%s' % bridge)
-    for ip in ipaddr:
-        args.append('ipaddr=%s' % ip)
-    return ' '.join(args)
-    
-def up(vif, **kwds):
-    """Call 'vifctl up' for a vif. Called when a vif is created.
-    """
-    args = vifctl_args(vif, **kwds)
-    os.system(VIFCTL + ' up ' + args)
+        args.append("bridge='%s'" % bridge)
+    if ipaddr:
+        ips = ' '.join(ipaddr)
+        args.append("ip='%s'" % ips)
+    args = ' '.join(args)
+    os.system(script + ' ' + args)
 
-def down(vif, **kwds):
-    """Call 'vifctl down' for a vif. Called when a vif is destroyed.
-    """
-    args = vifctl_args(vif, **kwds)
-    os.system(VIFCTL + ' down ' + args)
index 5dff09e388a316e6c8fa503125e784c916868157..89c1731fbc5bb3af56b2970d1b9434cbb321b0ab 100644 (file)
@@ -146,16 +146,6 @@ def make_disk(dom, uname, dev, mode, recreate=0):
     ctrl.addCallback(fn)
     return ctrl
         
-def make_vif(dom, vif, vmac, recreate=0):
-    """Create a virtual network device for a domain.
-
-    
-    @returns Deferred
-    """
-    xend.netif_create(dom, recreate=recreate)
-    d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate)
-    return d
-
 def vif_up(iplist):
     """send an unsolicited ARP reply for all non link-local IP addresses.
 
@@ -312,28 +302,28 @@ def append_deferred(dlist, v):
 
 def _vm_configure1(val, vm):
     d = vm.create_devices()
-    print '_vm_configure1> made devices...'
+    #print '_vm_configure1> made devices...'
     def cbok(x):
-        print '_vm_configure1> cbok', x
+        #print '_vm_configure1> cbok', x
         return x
     d.addCallback(cbok)
     d.addCallback(_vm_configure2, vm)
-    print '_vm_configure1<'
+    #print '_vm_configure1<'
     return d
 
 def _vm_configure2(val, vm):
-    print '>callback _vm_configure2...'
+    #print '>callback _vm_configure2...'
     d = vm.configure_fields()
     def cbok(results):
-        print '_vm_configure2> cbok', results
+        #print '_vm_configure2> cbok', results
         return vm
     def cberr(err):
-        print '_vm_configure2> cberr', err
+        #print '_vm_configure2> cberr', err
         vm.destroy()
         return err
     d.addCallback(cbok)
     d.addErrback(cberr)
-    print '<_vm_configure2'
+    #print '<_vm_configure2'
     return d
 
 class XendDomainInfo:
@@ -803,14 +793,11 @@ def vm_dev_vif(vm, val, index):
         raise VmError('vif: vif in netif backend domain')
     vif = index #todo
     vmac = sxp.child_value(val, "mac")
-    defer = make_vif(vm.dom, vif, vmac, vm.recreate)
+    xend.netif_create(vm.dom, recreate=vm.recreate)
+    defer = xend.netif_dev_create(vm.dom, vif, val, recreate=vm.recreate)
     def fn(id):
         dev = xend.netif_dev(vm.dom, vif)
-        devid = sxp.attribute(val, 'id')
-        if devid:
-            dev.setprop('id', devid)
-        bridge = sxp.child_value(val, "bridge")
-        dev.up(bridge)
+        dev.vifctl('up')
         vm.add_device('vif', dev)
         print 'vm_dev_vif> created', dev
         return id
index 665f5df29ee2747f43170baa49618f6082f50e7b..f0223896955df1401b6f3869006822168ff36c32 100644 (file)
@@ -41,6 +41,9 @@ class XendRoot:
     """Environment variable used to override config_default."""
     config_var     = "XEND_CONFIG"
 
+    """Where network control scripts live."""
+    network_script_dir = "/etc/xen"
+
     def __init__(self):
         self.rebooted = 0
         self.last_reboot = None
@@ -99,6 +102,7 @@ class XendRoot:
         return self.rebooted
 
     def configure(self):
+        print 'XendRoot>configure>'
         self.set_config()
         self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
         self.lastboot = self.get_config_value("lastboot", self.lastboot_default)
@@ -114,23 +118,27 @@ class XendRoot:
         The config file is a sequence of sxp forms.
         """
         self.config_path = os.getenv(self.config_var, self.config_default)
+        print 'XendRoot>set_config> config_path=', self.config_path
         if os.path.exists(self.config_path):
+            print 'XendRoot>set_config> loading'
             fin = file(self.config_path, 'rb')
             try:
                 config = sxp.parse(fin)
-                config.insert(0, 'config')
+                config.insert(0, 'xend-config')
                 self.config = config
             finally:
                 fin.close()
         else:
-            self.config = ['config']
+            print 'XendRoot>set_config> not found'
+            self.config = ['xend-config']
+        print 'XendRoot> config=', self.config
 
     def get_config(self, name=None):
         """Get the configuration element with the given name, or
         the whole configuration if no name is given.
 
-        name   element name (optional)
-        returns config or none
+        @param name: element name (optional)
+        @return: config or none
         """
         if name is None:
             val = self.config
@@ -141,12 +149,31 @@ class XendRoot:
     def get_config_value(self, name, val=None):
         """Get the value of an atomic configuration element.
 
-        name   element name
-        val    default value (optional, defaults to None)
-        returns value
+        @param name: element name
+        @param val:  default value (optional, defaults to None)
+        @return: value
         """
         return sxp.child_value(self.config, name, val=val)
 
+    def get_xend_port(self):
+        return int(self.get_config_value('xend-port', '8000'))
+
+    def get_xend_address(self):
+        return self.get_config_value('xend-address', '')
+
+    def get_network_script(self):
+        return self.get_config_value('network-script', 'network')
+
+    def get_vif_bridge(self):
+        return self.get_config_value('vif-bridge', 'xen-br0')
+
+    def get_vif_script(self):
+        return self.get_config_value('vif-script', 'vif-bridge')
+
+    def get_vif_antispoof(self):
+        v = self.get_config_value('vif-antispoof', 'yes')
+        return v in ['yes', '1', 'on']
+
 def instance():
     global inst
     try:
index c4e562e711ab82d7dd9dff22bf07ea9b901e1990..e80b23334e12b476d5bd8a921684ab111ad8d199 100644 (file)
@@ -734,15 +734,14 @@ class Daemon:
     def netif_get(self, dom):
         return self.netifCF.getInstanceByDom(dom)
 
-    def netif_dev_create(self, dom, vif, vmac, recreate=0):
+    def netif_dev_create(self, dom, vif, config, recreate=0):
         """Create a network device.
 
-        todo
         """
         ctrl = self.netifCF.getInstanceByDom(dom)
         if not ctrl:
             raise ValueError('No netif controller: %d' % dom)
-        d = ctrl.attachDevice(vif, vmac, recreate=recreate)
+        d = ctrl.attachDevice(vif, config, recreate=recreate)
         return d
 
     def netif_dev(self, dom, vif):
index ac201dd10d7525a2091ace329c0e4b6e97b296c3..9bc42f42175368e6a02af1c08f6b4b960f37ab77 100644 (file)
@@ -37,19 +37,18 @@ from xen.xend import Vifctl
 from SrvRoot import SrvRoot
 
 def create(port=None, interface=None, bridge=0):
-    if port is None: port = 8000
-    if interface is None: interface = ''
+    if port is None:
+        port = xroot.get_xend_port()
+    if interface is None:
+        interface = xroot.get_xend_address()
     if bridge or xroot.rebooted:
-        init_bridge()
+        Vifctl.network('start')
     root = resource.Resource()
     xend = SrvRoot()
     root.putChild('xend', xend)
     site = server.Site(root)
     reactor.listenTCP(port, site, interface=interface)
 
-def init_bridge():
-    Vifctl.init()
-
 def main(port=None, interface=None):
     create(port, interface)
     reactor.run()
index 415ab2409bb73bdd4cdd032de1f1bf846b0fab9b..4d3b854bedae746f827e1fe2292ebd5455c9a664 100755 (executable)
@@ -109,20 +109,42 @@ class NetDev(controller.Dev):
     """Info record for a network device.
     """
 
-    def __init__(self, ctrl, vif, mac):
+    def __init__(self, ctrl, vif, config):
         controller.Dev.__init__(self, ctrl)
         self.vif = vif
-        self.mac = mac
         self.evtchn = None
+        self.configure(config)
+
+    def configure(self, config):
+        self.config = config
+        self.mac = None
         self.bridge = None
-        self.ipaddr = []
+        self.script = None
+        self.ipaddr = None
+        
+        vmac = sxp.child_value(config, 'mac')
+        if not vmac: raise ValueError("invalid mac")
+        mac = [ int(x, 16) for x in vmac.split(':') ]
+        if len(mac) != 6: raise ValueError("invalid mac")
+        self.mac = mac
 
+        self.bridge = sxp.child_value(config, 'bridge')
+        self.script = sxp.child_value(config, 'script')
+
+        ipaddrs = sxp.children(config, elt='ip')
+        for ipaddr in ipaddrs:
+            self.ipaddr.append(sxp.child0(ipaddr))
+        
     def sxpr(self):
         vif = str(self.vif)
         mac = self.get_mac()
-        val = ['netdev', ['vif', vif], ['mac', mac]]
+        val = ['vif', ['idx', vif], ['mac', mac]]
         if self.bridge:
             val.append(['bridge', self.bridge])
+        if self.script:
+            val.append(['script', self.script])
+        for ip in self.ipaddr:
+            val.append(['ip', ip])
         if self.evtchn:
             val.append(['evtchn',
                         self.evtchn['port1'],
@@ -140,24 +162,22 @@ class NetDev(controller.Dev):
         return ':'.join(map(lambda x: "%x" % x, self.mac))
 
     def vifctl_params(self):
-        return { 'mac'   : self.get_mac(),
+        from xen.xend import XendDomain
+        xd = XendDomain.instance()
+        dom = self.controller.dom
+        dominfo = xd.domain_get(dom)
+        name = (dominfo and dominfo.name) or ('DOM%d' % dom)
+        return { 'domain': name,
+                 'vif'   : self.get_vifname(), 
+                 'mac'   : self.get_mac(),
                  'bridge': self.bridge,
-                 'ipaddr': self.ipaddr }
+                 'script': self.script,
+                 'ipaddr': self.ipaddr, }
 
-    def up(self, bridge=None, ipaddr=[]):
-        """Bring the device up.
-
-        bridge ethernet bridge to connect to
-        ipaddr list of ipaddrs to filter using iptables
+    def vifctl(self, op):
+        """Bring the device up or down.
         """
-        self.bridge = bridge
-        self.ipaddr = ipaddr
-        Vifctl.up(self.get_vifname(), **self.vifctl_params())
-
-    def down(self):
-        """Bring the device down.
-        """
-        Vifctl.down(self.get_vifname(), **self.vifctl_params())
+        Vifctl.vifctl(op, **self.vifctl_params())
 
     def destroy(self):
         """Destroy the device's resources and disconnect from the back-end
@@ -165,7 +185,7 @@ class NetDev(controller.Dev):
         """
         def cb_destroy(val):
             self.controller.send_be_destroy(self.vif)
-        self.down()
+        self.vifctl('down')
         #d = self.controller.factory.addDeferred()
         d = defer.Deferred()
         d.addCallback(cb_destroy)
@@ -194,24 +214,6 @@ class NetifController(controller.Controller):
         val = ['netif', ['dom', self.dom]]
         return val
     
-    def randomMAC(self):
-        """Generate a random MAC address.
-
-        Uses OUI (Organizationally Unique Identifier) AA:00:00, an
-        unassigned one that used to belong to DEC. The OUI list is
-        available at 'standards.ieee.org'.
-
-        The remaining 3 fields are random, with the first bit of the first
-        random field set 0.
-
-        returns array of 6 ints
-        """
-        mac = [ 0xaa, 0x00, 0x00,
-                random.randint(0x00, 0x7f),
-                random.randint(0x00, 0xff),
-                random.randint(0x00, 0xff) ]
-        return mac
-
     def lostChannel(self):
         """Method called when the channel has been lost.
         """
@@ -231,22 +233,15 @@ class NetifController(controller.Controller):
         """
         return self.devices.get(vif)
 
-    def addDevice(self, vif, vmac):
-        """Add a network interface. If vmac is None a random MAC is
-        assigned. If specified, vmac must be a string of the form
-        XX:XX:XX:XX:XX where X is hex digit.
+    def addDevice(self, vif, config):
+        """Add a network interface.
 
         vif device index
-        vmac device MAC 
+        config device configuration 
 
         returns device
         """
-        if vmac is None:
-            mac = self.randomMAC()
-        else:
-            mac = [ int(x, 16) for x in vmac.split(':') ]
-        if len(mac) != 6: raise ValueError("invalid mac")
-        dev = NetDev(self, vif, mac)
+        dev = NetDev(self, vif, config)
         self.devices[vif] = dev
         return dev
 
@@ -259,14 +254,14 @@ class NetifController(controller.Controller):
         for dev in self.getDevices():
             dev.destroy()
 
-    def attachDevice(self, vif, vmac, recreate=0):
+    def attachDevice(self, vif, config, recreate=0):
         """Attach a network device.
         If vmac is None a random mac address is assigned.
 
         @param vif interface index
         @param vmac mac address (string)
         """
-        self.addDevice(vif, vmac)
+        self.addDevice(vif, config)
         d = defer.Deferred()
         if recreate:
             d.callback(self)
index 223a9f560214ff829149d683a2f08d0014cfbfbf..9e2975d24e2f2141b7ee1ac4a602b0fcda92ad2c 100644 (file)
@@ -2,6 +2,7 @@
 
 """Domain creation.
 """
+import random
 import string
 import sys
 
@@ -127,11 +128,13 @@ gopts.var('ipaddr', val="IPADDR",
          fn=append_value, default=[],
          use="Add an IP address to the domain.")
 
-gopts.var('vif', val="mac=MAC,bridge=BRIDGE",
+gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT",
          fn=append_value, default=[],
          use="""Add a network interface with the given MAC address and bridge.
+         The vif is configured by calling the given configuration script.
          If mac is not specified a random MAC address is used.
          If bridge is not specified the default bridge is used.
+         If script is not specified the default script is used.
          This option may be repeated to add more than one vif.
          Specifying vifs will increase the number of interfaces as needed.
          """)
@@ -227,6 +230,24 @@ def configure_pci(config_devs, vals):
         config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
         config_devs.append(['device', config_pci])
 
+def randomMAC():
+    """Generate a random MAC address.
+
+    Uses OUI (Organizationally Unique Identifier) AA:00:00, an
+    unassigned one that used to belong to DEC. The OUI list is
+    available at 'standards.ieee.org'.
+
+    The remaining 3 fields are random, with the first bit of the first
+    random field set 0.
+
+    returns array of 6 ints
+    """
+    mac = [ 0xaa, 0x00, 0x00,
+            random.randint(0x00, 0x7f),
+            random.randint(0x00, 0xff),
+            random.randint(0x00, 0xff) ]
+    return ':'.join(map(lambda x: "%x" % x, mac))
+
 def configure_vifs(config_devs, vals):
     """Create the config for virtual network interfaces.
     """
@@ -238,14 +259,17 @@ def configure_vifs(config_devs, vals):
             d = vifs[idx]
             mac = d.get('mac')
             bridge = d.get('bridge')
+            script = d.get('script')
         else:
-            mac = None
+            mac = randomMAC()
             bridge = None
+            script = None
         config_vif = ['vif']
-        if mac:
-            config_vif.append(['mac', mac])
+        config_vif.append(['mac', mac])
         if bridge:
             config_vif.append(['bridge', bridge])
+        if script:
+            config_vif.append(['script', script])
         config_devs.append(['device', config_vif])
 
 def configure_vfr(config, vals):